package com.google.code.lf.commons.util;

import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import com.google.code.lf.commons.exception.InvalidArgumentException;
import com.google.code.lf.commons.exception.NullArgumentException;

/**
 * Classe regroupant des méthodes utilitaires pour manipulation de {@link File}.
 * 
 * @author gael.lorent-fonfrede
 */
public class FileHelper {
	/**
	 * Constructeur. Ne doit pas être appelé.
	 * @throws UnsupportedOperationException Toujours.
	 */
	private FileHelper() {
		throw new UnsupportedOperationException("Classe utilitaire, ne doit pas être instanciée.");
	}

	/**
	 * Vérifie qu'un fichier est bien de type fichier et est lisible s'il existe.
	 * 
	 * @param file La référence de {@link File} à valider.
	 */
	public static void checkFileIsReadable(final File file) {
		if (file == null) throw new NullArgumentException("file");
		if (file.exists() && !file.isFile()) throw new InvalidArgumentException("file", "File exists but is not of type 'file'");
		if (file.exists() && !file.canRead()) throw new InvalidArgumentException("file", "File exists but is not readable");
	}

	/**
	 * Vérifie qu'un fichier est bien de type fichier et est inscriptible s'il existe.
	 * 
	 * @param file La référence de {@link File} à valider.
	 * 
	 * @see #checkFileIsReadable(File)
	 */
	public static void checkFileIsWritable(final File file) {
		FileHelper.checkFileIsReadable(file);
		if (file.exists() && !file.canWrite()) throw new InvalidArgumentException("file", "File exists but is not writable");
	}

	/**
	 * Vérifie qu'un fichier existe, est bien de type fichier et est lisible.
	 * 
	 * @param file La référence de {@link File} à valider.
	 * 
	 * @see #checkFileIsReadable(File)
	 */
	public static void checkFileExistsAndIsReadable(final File file) {
		FileHelper.checkFileIsReadable(file);
		if (!file.exists()) throw new InvalidArgumentException("file", "File does not exist");
	}

	/**
	 * Vérifie qu'un fichier existe, est bien de type fichier et est inscriptible.
	 * 
	 * @param file La référence de {@link File} à valider.
	 * 
	 * @see #checkFileExistsAndIsReadable(File)
	 */
	public static void checkFileExistsAndIsWritable(final File file) {
		FileHelper.checkFileExistsAndIsReadable(file);
		if (!file.canWrite()) throw new InvalidArgumentException("file", "File is not writable");
	}

	/**
	 * Charge un fichier à partir de son nom dans le classpath.
	 * 
	 * @param fileName Nom du fichier à charger.
	 * @return Le {@link File} initialisé.
	 */
	public static File loadFileFromClasspath(final String fileName) {
		// Recherche de l'URL dans le classpath
		final URL fileUrl = Thread.currentThread().getContextClassLoader().getResource(fileName);
		if (fileUrl == null) throw new InvalidArgumentException("fileName", new StringBuilder("No ressource found in classpath for fileName: ").append(fileName).append(".").toString());

		// Transformation en URI
		URI fileUri = null;
		try {
			fileUri = fileUrl.toURI();
		} catch (final URISyntaxException e) {
			e.printStackTrace();
			throw new RuntimeException("URISyntaxException raised: " + e.getMessage(), e);
		}

		// Retourner le File
		return new File(fileUri);
	}
}
